<?php
namespace App\Module\Pay\Service;

use App\Component\Wechat\WechatFactory;
use App\Constants\Constant;
use App\Exception\AppException;
use App\Model\Activity;
use App\Model\ActivityUserMid;
use App\Model\Payment;
use App\Model\User;
use App\Model\UserScoreDetail;
use App\Module\Pay\Request\ActivityRequest;
use Hyperf\Contract\ConfigInterface;
use Hyperf\Di\Annotation\Inject;
use Qbhy\HyperfAuth\AuthManager;

class ActivityService {

    /**
     * @Inject()
     * @var AuthManager $authManager
     */
    private $authManager;

    /**
     * @Inject()
     * @var WechatFactory $wechatFactory
     */
    private $wechatFactory;

    /**
     * @Inject()
     * @var ConfigInterface $configInterface
     */
    private $configInterface;

    public function pay(ActivityRequest $request){
        $activity = Activity::query()->findOrFail($request->input("act_id"));

        //是否正在活动
        if(!$activity->is_start){
            throw new AppException("活动以结束");
        }

        $user = $this->authManager->guard(Constant::USER)->user();

        $cash_price = $activity->fee;
        //启用积分兑换
        if($activity->score == Constant::GLOBAL_TRUE){
            //大于活动最大抵扣额
            if($request->input("score") > $activity->getAttribute("score_content")['max']){
                throw new AppException("抵扣积分不能大于活动可抵扣积分");
            }
            //大于自身可用积分
            if($request->input("score") > $user->score->available){
                throw new AppException("抵扣积分不能大于自身可用积分");
            }
            $cash_price = round($activity->fee - ($request->input("score") / $activity->getAttribute("score_content")['rate']),2);
            if($cash_price < 0){
                $cash_price = 0;
            }
        }

        $platform_trade_no = date("YmdHis") . random_int(1000,9999);

        $payment = new Payment();
        $payment->setAttribute("user_id",$user->user_id);
        $payment->setAttribute("origin",Constant::ORIGIN_ACTIVITY);
        $payment->setAttribute("source_id",$activity->act_id);
        $payment->setAttribute("total_fee",$activity->fee);
        $payment->setAttribute("cash_fee",$cash_price);
        $payment->setAttribute("score",$request->input("score"));
        $payment->setAttribute("platform_trade_no",$platform_trade_no);
        $payment->setAttribute("attach",[
            'act_name'=>$activity->getAttribute("act_name"),
            'share_id'=>$request->input("share_id",0),
            'child_name'=>$request->input("child_name"),
            'parent_name'=>$request->input("parent_name"),
            'parent_mobile'=>$request->input("parent_mobile")
        ]);

        $pay_params = [];
        if($cash_price == 0){
            $payment->setAttribute("channel",Constant::PAY_CHANNEL_SCORE);
            $pay_params['needPay']='N';
            $payment->save();
            $this->payUpdate($platform_trade_no);
        }else{
            $payment->setAttribute("channel",Constant::PAY_CHANNEL_WECHAT);
            $payment->save();
            $pay_params = $this->wechatFactory->getPayment()->jssdk->bridgeConfig($this->wechatFactory->getPayment()->order->unify([
                'body'=>$activity->act_name ."活动",
                'out_trade_no'=>$platform_trade_no,
                'total_fee'=>($this->configInterface->get("wechat.payment.sandbox") ? 1.01 : $cash_price) * 100,
                'notify_url'=>$this->configInterface->get("wechat.payment.notify_url"),
                'trade_type'=>'JSAPI',
                'openid'=>$user->wechatInfo->openid
            ])['prepay_id'],false);
            $pay_params['needPay'] = "Y";
        }

        return $pay_params;
    }

    //支付成功后更新：订单状态、积分、活动
    public function payUpdate($platform_trade_no, $channel_trade_no=""){
        //订单状态
        $payment = Payment::query()->where("platform_trade_no",$platform_trade_no)->firstOrFail();
        $payment->setAttribute("channel_trade_no",$channel_trade_no);
        $payment->setAttribute("pay_status",Constant::PAY_STATUS_SUCCESS);
        $payment->setAttribute("order_status",Constant::ORDER_STATUS_UNUSE);
        $payment->save();

        //活动
        $activity = Activity::query()->findOrFail($payment->source_id);
        $activity_user_mid = new ActivityUserMid();
        $activity_user_mid->setAttribute("act_id",$payment->source_id);
        $activity_user_mid->setAttribute("user_id",$payment->user_id);
        $activity_user_mid->save();
        #团购、抢购是否到达最大人数
        if(in_array($activity->type,[Constant::ACTIVITY_TYPE_GROUP,Constant::ACTIVITY_TYPE_SPEED]) && ActivityUserMid::query()->where("act_id",$payment->source_id)->count() >= $activity->getAttribute("type_content")['max']){
            $activity->setAttribute("status",Constant::ACTIVITY_STATUS_FINISH);
        }
        $activity->save();

        //下单人积分
        if($payment->getAttribute("score") != 0){
            $user_score = $payment->user->score;
            $user_score->available -= $payment->score;
            $user_score->consume += $payment->score;
            $user_score_detail = new UserScoreDetail();
            $user_score_detail->setAttribute("user_id",$user_score->user_id);
            $user_score_detail->setAttribute("direction",Constant::DIRECTION_DEC);
            $user_score_detail->setAttribute("origin",Constant::SCORE_ORIGIN_ACTIVITY_JOIN);
            $user_score_detail->setAttribute("source_id",$payment->source_id);
            $user_score_detail->setAttribute("score",$payment->score);
            $user_score_detail->setAttribute("remark","参加".$payment->getAttribute("attach")['act_name']."活动");
            $user_score->save() && $user_score_detail->save();
        }

        //分享人积分
        if($payment->getAttribute("attach")['share_id'] != 0){
            //活动对分享人是否参加了活动做不同的积分奖励
            $inc_score = Payment::query()->where([
                ['user_id',$payment->getAttribute("attach")['share_id']],
                ['source_id',$payment->getAttribute("source_id")],
                ['pay_status',Constant::PAY_STATUS_SUCCESS]
            ])->exists() ? $activity->getAttribute("share_content")['join'] : $activity->getAttribute("share_content")['see'];
            $share_score = User::query()->findOrFail($payment->getAttribute("attach")['share_id'])->score;
            $share_score->total += $inc_score;
            $share_score->available += $inc_score;
            $share_score_detail = new UserScoreDetail();
            $share_score_detail->setAttribute("user_id",$share_score->user_id);
            $share_score_detail->setAttribute("direction",Constant::DIRECTION_INC);
            $share_score_detail->setAttribute("origin",Constant::SCORE_ORIGIN_ACTIVITY_JOIN);
            $share_score_detail->setAttribute("source_id",$payment->source_id);
            $share_score_detail->setAttribute("score",$inc_score);
            $share_score_detail->setAttribute("remark",$payment->user->username . "参加" .$payment->getAttribute("attach")['act_name'] . "活动");
            $share_score->save() && $share_score_detail->save();
        }
    }
}